home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / common / los.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  17KB  |  676 lines

  1. /*
  2.  * static char *rcsid_los_c =
  3.  *   "$Id: los.c,v 1.17 1996/01/02 11:02:32 master Exp $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to frankj@ifi.uio.no.
  26.  
  27.     This file was made based on an idea by vidarl@ifi.uio.no
  28. */
  29.  
  30. /* Nov 95 - inserted USE_LIGHTING code stuff in here - b.t. */
  31.  
  32. #include <global.h>
  33. #include <funcpoint.h>
  34.  
  35.  
  36. typedef struct blstr {
  37.   int x[4],y[4],b[4];
  38.   int index;
  39. } blocks;
  40.  
  41. blocks block[11][11];
  42.  
  43. /*
  44.  * Used to initialise the array used by the LOS routines.
  45.  */
  46.  
  47. void set_block(int x,int y,int bx, int by) {
  48.   int index=block[x][y].index;
  49.   block[x][y].x[index]=bx;
  50.   block[x][y].y[index]=by;
  51.   block[x][y].index++;
  52. }
  53.  
  54. /*
  55.  * initialises the array used by the LOS routines.
  56.  */
  57.  
  58. void init_block() {
  59.   int x,y;
  60.   for(x=0;x<11;x++)
  61.     for(y=0;y<11;y++) {
  62.     block[x][y].index=0;
  63.     }
  64.  
  65. /* region 1 */
  66.  
  67.   set_block(5,4,4,3);
  68.   set_block(5,4,5,3);
  69.   set_block(5,4,6,3);
  70.   set_block(4,3,4,2);
  71.   set_block(5,3,5,2);
  72.   set_block(6,3,6,2);
  73.   set_block(4,2,4,1);
  74.   set_block(4,2,3,1);
  75.   set_block(5,2,5,1);
  76.   set_block(6,2,6,1);
  77.   set_block(6,2,7,1);
  78.   set_block(3,1,3,0);
  79.   set_block(4,1,4,0);
  80.   set_block(5,1,5,0);
  81.   set_block(6,1,6,0);
  82.   set_block(7,1,7,0);
  83.  
  84. /* region 2  */
  85.  
  86.   set_block(6,4,7,3);
  87.   set_block(7,3,7,2);
  88.   set_block(7,3,8,2);
  89.   set_block(7,3,8,3);
  90.   set_block(7,2,8,1);
  91.   set_block(8,2,9,1);
  92.   set_block(8,3,9,2);
  93.   set_block(8,1,8,0);
  94.   set_block(8,1,9,0);
  95.   set_block(9,1,10,0);
  96.   set_block(9,2,10,1);
  97.   set_block(9,2,10,2);
  98.  
  99. /* region 3  */
  100.  
  101.   set_block(6,5,7,4);
  102.   set_block(6,5,7,5);
  103.   set_block(6,5,7,6);
  104.   set_block(7,4,8,4);
  105.   set_block(7,5,8,5);
  106.   set_block(7,6,8,6);
  107.   set_block(8,4,9,3);
  108.   set_block(8,4,9,4);
  109.   set_block(8,5,9,5);
  110.   set_block(8,6,9,6);
  111.   set_block(8,6,9,7);
  112.   set_block(9,3,10,3);
  113.   set_block(9,4,10,4);
  114.   set_block(9,5,10,5);
  115.   set_block(9,6,10,6);
  116.   set_block(9,7,10,7);
  117.  
  118. /* region 4  */
  119.  
  120.   set_block(6,6,7,7);
  121.   set_block(7,7,8,7);
  122.   set_block(7,7,8,8);
  123.   set_block(7,7,7,8);
  124.   set_block(8,7,9,8);
  125.   set_block(8,8,9,9);
  126.   set_block(7,8,8,9);
  127.   set_block(9,8,10,8);
  128.   set_block(9,8,10,9);
  129.   set_block(9,9,10,10);
  130.   set_block(8,9,9,10);
  131.   set_block(8,9,8,10);
  132.  
  133. /* region 5  */
  134.  
  135.   set_block(5,6,4,7);
  136.   set_block(5,6,5,7);
  137.   set_block(5,6,6,7);
  138.   set_block(4,7,4,8);
  139.   set_block(5,7,5,8);
  140.   set_block(6,7,6,8);
  141.   set_block(4,8,3,9);
  142.   set_block(4,8,4,9);
  143.   set_block(5,8,5,9);
  144.   set_block(6,8,6,9);
  145.   set_block(6,8,7,9);
  146.   set_block(3,9,3,10);
  147.   set_block(4,9,4,10);
  148.   set_block(5,9,5,10);
  149.   set_block(6,9,6,10);
  150.   set_block(7,9,7,10);
  151.  
  152. /* region 6 */
  153.  
  154.   set_block(4,6,3,7);
  155.   set_block(3,7,2,7);
  156.   set_block(3,7,2,8);
  157.   set_block(3,7,3,8);
  158.   set_block(2,7,1,8);
  159.   set_block(2,8,1,9);
  160.   set_block(3,8,2,9);
  161.   set_block(1,8,0,8);
  162.   set_block(1,8,0,9);
  163.   set_block(1,9,0,10);
  164.   set_block(2,9,1,10);
  165.   set_block(2,9,2,10);
  166.  
  167. /* region 7 */
  168.  
  169.   set_block(4,5,3,4);
  170.   set_block(4,5,3,5);
  171.   set_block(4,5,3,6);
  172.   set_block(3,4,2,4);
  173.   set_block(3,5,2,5);
  174.   set_block(3,6,2,6);
  175.   set_block(2,4,1,3);
  176.   set_block(2,4,1,4);
  177.   set_block(2,5,1,5);
  178.   set_block(2,6,1,6);
  179.   set_block(2,6,1,7);
  180.   set_block(1,3,0,3);
  181.   set_block(1,4,0,4);
  182.   set_block(1,5,0,5);
  183.   set_block(1,6,0,6);
  184.   set_block(1,7,0,7);
  185.  
  186. /* region 8 */
  187.  
  188.   set_block(4,4,3,3);
  189.   set_block(3,3,3,2);
  190.   set_block(3,3,2,2);
  191.   set_block(3,3,2,3);
  192.   set_block(3,2,2,1);
  193.   set_block(2,2,1,1);
  194.   set_block(2,3,1,2);
  195.   set_block(2,1,1,0);
  196.   set_block(2,1,2,0);
  197.   set_block(1,1,0,0);
  198.   set_block(1,2,0,1);
  199.   set_block(1,2,0,2);
  200. }
  201.  
  202. /*
  203.  * Used to initialise the array used by the LOS routines.
  204.  */
  205.  
  206. void set_wall(object *op,int x,int y) {
  207.   int i;
  208.   for(i=0;i<block[x][y].index;i++) {
  209.     int dx=block[x][y].x[i],dy=block[x][y].y[i];
  210.     op->contr->blocked_los[dx][dy]=1;
  211.     set_wall(op,dx,dy);
  212.   }
  213. }
  214.  
  215. /*
  216.  * Used to initialise the array used by the LOS routines.
  217.  */
  218.  
  219. void check_wall(object *op,int x,int y) {
  220.   if(!block[x][y].index)
  221.     return;
  222.   if(blocks_view(op->map,op->x-5+x,op->y-5+y))
  223.     set_wall(op,x,y);
  224.   else {
  225.     int i;
  226.     for(i=0;i<block[x][y].index;i++)
  227.       check_wall(op,block[x][y].x[i],block[x][y].y[i]);
  228.   }
  229. }
  230.  
  231. /*
  232.  * Clears/initialises the los-array associated to the player
  233.  * controlling the object.
  234.  */
  235.  
  236. void clear_los(object *op) {
  237.   (void)memset((void *) op->contr->blocked_los,0,
  238.                (WINRIGHT-WINLEFT+1)*(WINLOWER-WINUPPER+1));
  239. }
  240.  
  241. /* change_map_light() - used to change map light level (darkness)
  242.  * up or down by *1*. This fctn is not designed to change by
  243.  * more than that!  Returns true if successful. -b.t. */
  244.  
  245. int change_map_light(mapstruct *m, int change) {
  246.   int new_level = m->darkness + change;
  247.  
  248.   if(new_level<=0) {
  249.         m->darkness = 0;
  250.         return 0;
  251.   }
  252.  
  253.   if(new_level>MAX_DARKNESS) return 0;
  254.  
  255.   if(change) {
  256.      char buf[MAX_BUF];
  257.  
  258.      if(change>0) sprintf(buf,"It becomes darker.");
  259.      else sprintf(buf,"It becomes brighter.");
  260.  
  261.      /* inform all players on the map */
  262.      (info_map_func)(NDI_BLACK, m,buf);
  263.  
  264.      m->darkness=m->map_object->invisible=new_level;
  265.      m->do_los=0; /* to insure that los is updated */
  266.      update_all_los(m);
  267.      return 1;
  268.   }
  269.  
  270.   return 0;
  271. }
  272.  
  273. /*
  274.  * expand_sight goes through the array of what the given player is
  275.  * able to see, and expands the visible area a bit, so the player will,
  276.  * to a certain degree, be able to see into corners.
  277.  * This is somewhat suboptimal, would be better to improve the formula.
  278.  * There are two versions of this function, based on whether or not
  279.  * CD_LINE_OF_SIGHT is defined.  If it is defined, the function
  280.  * becomes a bit more time-consuming, but covers a few more "corners"...
  281.  */
  282.  
  283.  
  284. void expand_sight(object *op) 
  285. {
  286.   int i,x,y, dx, dy;
  287.  
  288.   for(x=1;x<10;x++)    /* loop over inner squares */
  289.     for(y=1;y<10;y++)
  290.       if(!op->contr->blocked_los[x][y]&&
  291.          !blocks_view(op->map,op->x-5+x,op->y-5+y))
  292.         for(i=1;i<=8;i+=1) {    /* mark all directions */
  293.           dx = x + freearr_x[i];
  294.       dy = y + freearr_y[i];
  295.           if(op->contr->blocked_los[dx][dy] > 0) /* for any square blocked */
  296.             op->contr->blocked_los[dx][dy]= -1;
  297.     }
  298.  
  299. #ifdef USE_LIGHTING
  300.   if(op->map->do_los) update_map_lights(op->map);
  301.   if(op->map->darkness>0)  /* player is on a dark map */
  302.       expand_lighted_sight(op);
  303. #endif
  304.  
  305.   /* clear mark squares */
  306.   for (x = 0; x < 11; x++)
  307.     for (y = 0; y < 11; y++)
  308.       if (op->contr->blocked_los[x][y] < 0)
  309.             op->contr->blocked_los[x][y] = 0;
  310. }
  311.  
  312. void add_light_to_list (object *light, object *op) {
  313.   objectlink *obl=get_objectlink();
  314.  
  315.   if(!light||light->glow_radius<1||QUERY_FLAG(light, FLAG_FREED)) return;
  316.  
  317.   obl = (objectlink *) malloc(sizeof(objectlink));
  318.   obl->ob = light;
  319.   obl->id = light->count;
  320.   obl->next = op->lights;
  321.   op->lights = obl;
  322.   LOG(llevDebug,"Adding light %s (%d) to op %s light list\n"
  323.     ,light->name,light->count,op->name);
  324.  
  325. }
  326.  
  327.  
  328. void remove_light_from_list(object *light, object *op) {
  329.   objectlink *obl=op->lights,*first,*prev=NULL,*nxt;
  330.  
  331.   if(!light||QUERY_FLAG(light, FLAG_FREED)) return;
  332.  
  333.   prev=first=obl;
  334.   while(obl) {
  335.      nxt = obl->next ? obl->next: NULL;
  336.      if(obl->id==light->count) {
  337.           if(obl==first) {
  338.               op->lights = nxt;
  339.               nxt = (nxt&&nxt->next) ? nxt->next: NULL;
  340.           }
  341.           if(prev) prev->next = nxt;
  342. #ifdef DEBUG_LIGHTS
  343.           LOG(llevDebug,"Removing light from op list: %s (%d)\n",
  344.         light->name,light->count);
  345. #endif
  346.           CFREE(obl);
  347.       obl = NULL;
  348.           return;
  349.      } else
  350.           prev = obl;
  351.      obl=nxt;
  352.   }
  353.  
  354.   /* light not found! */
  355.   LOG(llevError,"Couldnt remove requested light %s (%d) from op list\n",
  356.         light->name, light->count);
  357.   if(first) op->lights = first;
  358. }
  359.  
  360. /* returns true if op carries one or more lights */
  361.  
  362. int has_carried_lights(object *op) {
  363.   objectlink *obl;
  364.   object *tmp=NULL;
  365.  
  366.   /* op may glow! */
  367.   if(op->glow_radius>0) return 1;
  368.  
  369.   /* carried items */
  370.   for(obl=op->lights;obl;obl=obl->next)
  371.      if((tmp=obl->ob)&&!QUERY_FLAG(tmp,FLAG_FREED)&&obl->id>0) 
  372.        return 1;
  373.  
  374.   return 0;
  375. }
  376.  
  377. /* called when a player/pet monster changes maps, and has lights */
  378.  
  379. void add_carried_lights(object *pl) {
  380.   objectlink *obl;
  381.   object *tmp=NULL;
  382.  
  383.   /* pl may glow! */
  384.   if(pl->glow_radius>0) add_light_to_map(pl,pl->map);
  385.  
  386.   /* carried items */
  387.   for(obl=pl->lights;obl;obl=obl->next) {    
  388.         if((tmp=obl->ob)&&!QUERY_FLAG(tmp,FLAG_FREED)&&obl->id>0) { 
  389. #ifdef DEBUG_LIGHTS
  390.            LOG(llevDebug,"got carried light: %s (%d)\n",tmp->name,tmp->count); 
  391. #endif
  392.            add_light_to_map(tmp,pl->map);
  393.     }
  394.   } 
  395.  
  396. void remove_carried_lights(object *pl, mapstruct *map) {
  397.   objectlink *obl=get_objectlink(),*maplight;
  398.  
  399.   for(obl=pl->lights;obl;obl=obl->next)
  400.      for(maplight=map->light;maplight;maplight=maplight->next) { 
  401.     if(maplight->id==obl->id) maplight->id = -1;
  402.      }
  403.   if(pl->lights) update_map_lights(map);
  404. }
  405.  
  406.  
  407. void add_light_to_map(object *ob, mapstruct *map) {
  408.   objectlink *obl=get_objectlink();   
  409.  
  410.   if(ob->arch == NULL) { 
  411.     LOG(llevError,"Can't add light %s (%d) without arch\n",ob->name,obl->id);
  412.     return;
  413.   } 
  414. #ifdef DEBUG_LIGHTS
  415.   LOG(llevDebug,"Adding light source: %s (%d) to maplist %s\n"
  416.         ,ob->name,ob->count,map->path);
  417. #endif   
  418.   obl = (objectlink *) malloc(sizeof(objectlink));
  419.   obl->ob = ob;  
  420.   obl->id = ob->count;   
  421.   obl->next = map->light;
  422.   map->light=obl;
  423.  
  424.   update_all_los(map);
  425. }
  426.  
  427. /* light_not_listed()- check to see if the light is already on the map list 
  428.  * returns true if the light is not listed */ 
  429.  
  430. int light_not_listed(object *op) {
  431.    objectlink *obl=NULL;
  432.  
  433.    if(!op->map)
  434.     if(op->env&&op->env->map) 
  435.         obl=op->env->map->light;
  436.     else { 
  437.         LOG(llevError,"Error: can't find map light list in light_not_listed()\n");
  438.         return 0; 
  439.     }
  440.    else 
  441.      obl=op->map->light;
  442.    while(obl) {
  443.      if(obl->id==op->count) return 0;
  444.      obl=obl->next;
  445.    } 
  446.    return 1;
  447. }
  448.  
  449. /* update_map_lights() - traverse linked list of lights, and 
  450.  * remove those objects which were freed. -b.t.
  451.  */
  452.  
  453. void update_map_lights(mapstruct *m) {
  454.   objectlink *obl=m->light,*prev,*first,*nxt=NULL;
  455.   object *tmp=NULL;
  456.  
  457.   prev=first=obl;
  458.   while(obl) {
  459.      nxt = obl->next ? obl->next: NULL;
  460.      if(!(tmp=obl->ob)||(obl->id!=tmp->count)||QUERY_FLAG(tmp,FLAG_FREED)
  461.     ||tmp->glow_radius<1) {
  462.       if(obl==first) { 
  463.           first = prev = nxt;
  464.                nxt = (nxt&&nxt->next) ? nxt->next: NULL;
  465.       }
  466.       if(prev) prev->next = nxt;
  467. #ifdef DEBUG_LIGHTS
  468.         if(tmp) LOG(llevDebug,"Removing light from map list: %s (%d)\n"
  469.         ,tmp->name,tmp->count);
  470.         else LOG(llevDebug,"Removing null light (%d) from map list.\n",
  471.         obl->id);
  472. #endif
  473.           CFREE(obl);
  474.       obl = NULL;
  475.      } else
  476.       prev = obl;
  477.      obl=nxt;
  478.   }
  479.   if(first)
  480.      m->light = first;
  481.   else     
  482.      m->light = NULL;
  483.  
  484.   m->do_los = 0;
  485. }
  486.  
  487. void expand_lighted_sight(object *op)
  488. {
  489.   int x,y,dx,dy,radius=0,darklevel;
  490.   object *tmp=NULL;
  491.   mapstruct *m=op->map;
  492.   objectlink *light=m->light;
  493.  
  494.   darklevel = MAP_DARKNESS(m);
  495.  
  496. /* If the player can see in the dark, lower the darklevel for him */ 
  497.  
  498.   if(QUERY_FLAG(op,FLAG_SEE_IN_DARK)) darklevel -= 2;
  499.  
  500. /* add light, by finding all (non-null) nearby light sources, then 
  501.  * mark those squares specially. If the darklevel<1, there is no
  502.  * reason to do this, so we skip this function */
  503.  
  504.   if(darklevel<1) return;
  505.  
  506.   for(light=m->light;light!=NULL;light=light->next) { 
  507.     if(!(tmp=light->ob)||tmp->count!=light->id
  508.        ||tmp->glow_radius<1||QUERY_FLAG(tmp,FLAG_FREED)) continue;
  509.  
  510.     /* if the light is not carried by a live creature *or* if its 
  511.      * on the map but its not the top object we ignore it (unless 
  512.      * its invisible). This helps to speed up the game. */
  513.  
  514.     if(!tmp->env&&tmp->above&&!tmp->invisible) continue;
  515.  
  516.       /* which coordinates to use for the light */ 
  517.         if(!tmp->env) /* use map coord */
  518.            dx=abs(tmp->x-op->x),dy=abs(tmp->y-op->y);
  519.         else /* light is held, use env coord */
  520.            dx=abs(tmp->env->x-op->x),dy=abs(tmp->env->y-op->y);
  521.  
  522.         radius = BRIGHTNESS(tmp);
  523.  
  524.     /* ok, lets do it if in viewable range */
  525.     if(dx<=(4+radius)&&dy<=(4+radius)) {
  526.           int basex,basey;
  527.           if(!tmp->env) { /* get right coord for the light */
  528.         basex=tmp->x-op->x+5,basey=tmp->y-op->y+5;
  529.            } else { 
  530.         basex=tmp->env->x-op->x+5,basey=tmp->env->y-op->y+5;
  531.           }
  532.           radius-=1;  /* so we get right size illumination */ 
  533.  
  534.           for(x=-radius;x<=radius;x++) 
  535.             for(y=-radius;y<=radius;y++) {
  536.           /* round corners */
  537.           if(radius>1&&(abs(x)==radius)&&(abs(y)==radius)) continue; 
  538.               dx=basex+x,dy=basey+y;
  539.            if(dx>=0&&dx<11&&dy>=0&&dy<11
  540.             &&!op->contr->blocked_los[dx][dy])
  541.                          op->contr->blocked_los[dx][dy]= -2;
  542.                }
  543.         }
  544.   }
  545.  
  546.  
  547.   /* Now, limit player furthest (unlighted) vision */
  548.   for (x = 0; x < 11; x++)
  549.     for (y = 0; y < 11; y++)
  550.       if((x<darklevel||x>(10-darklevel))
  551.         ||(y<darklevel||y>(10-darklevel)))
  552.              if(op->contr->blocked_los[x][y]!=-2)
  553.           op->contr->blocked_los[x][y]= 1;
  554.  
  555. }
  556.  
  557. /* blinded_sight() - sets all veiwable squares to blocked except 
  558.  * for the one the central one that the player occupies 
  559.  */
  560.  
  561. void blinded_sight (object *op) {
  562.   int x,y;
  563.  
  564.   for (x = 0; x < 11; x++)
  565.     for (y = 0; y < 11; y++)
  566.     op->contr->blocked_los[x][y] = 1;
  567.  
  568.   op->contr->blocked_los[5][5] = 0;
  569. }
  570.  
  571. /*
  572.  * update_los() recalculates the array which specifies what is
  573.  * visible for the given player-object.
  574.  */
  575.  
  576. void update_los(object *op) {
  577.   int i;
  578.   if(QUERY_FLAG(op,FLAG_REMOVED))
  579.     return;
  580.   clear_los(op);
  581.   if(QUERY_FLAG(op,FLAG_WIZ) /* ||XRAYS(op) */)
  582.     return;
  583.   for(i=1;i<9;i++)
  584.     check_wall(op,5+freearr_x[i],5+freearr_y[i]);
  585.  
  586.   /* do the los of the player. 3 (potential) cases */
  587.   if(QUERY_FLAG(op,FLAG_BLIND)) /* player is blind */ 
  588.     blinded_sight(op);
  589.   else                
  590.     expand_sight(op);
  591.  
  592.   if (QUERY_FLAG(op,FLAG_XRAYS)) {
  593.     int x, y;
  594.     for (x = -2; x <= 2; x++)
  595.       for (y = -2; y <= 2; y++)
  596.         op->contr->blocked_los[5 + x][5 + y] = 0;
  597.   }
  598. }
  599.  
  600. /*
  601.  * This function makes sure that update_los() will be called for all
  602.  * players on the given map within the next frame.
  603.  * It is triggered by removal or inserting of objects which blocks
  604.  * the sight in the map.
  605.  */
  606.  
  607. void update_all_los(mapstruct *map) {
  608.   player *pl;
  609.  
  610. #ifdef USE_LIGHTING
  611.   if(map->do_los) return; /* we already did this */
  612.   map->do_los = 1;
  613. #endif
  614.   for(pl=first_player;pl!=NULL;pl=pl->next)
  615.     if(pl->ob->map==map)
  616.       pl->do_los=1;
  617. }
  618.  
  619. /*
  620.  * Debug-routine which dumps the array which specifies the visible
  621.  * area of a player.  Triggered by the z key in DM mode.
  622.  */
  623.  
  624. void print_los(object *op) {
  625.   int x,y;
  626.   char buf[50], buf2[10];
  627.  
  628.   strcpy(buf,"   ");
  629.   for(x=0;x<11;x++)
  630.   {
  631.     sprintf(buf2,"%2d",x);
  632.     strcat(buf,buf2);
  633.   }
  634.   (*draw_info_func)(NDI_UNIQUE, 0, op, buf);
  635.   for(y=0;y<11;y++) {
  636.     sprintf(buf,"%2d:",y);
  637.     for(x=0;x<11;x++)
  638.     {
  639.       sprintf(buf2," %1d",op->contr->blocked_los[x][y]);
  640.       strcat(buf,buf2);
  641.     }
  642.     (*draw_info_func)(NDI_UNIQUE, 0, op, buf);
  643.   }
  644. }
  645.  
  646. /*
  647.  * make_sure_seen: The object is supposed to be visible through walls, thus
  648.  * check if any players are nearby, and edit their LOS array.
  649.  */
  650.  
  651. void make_sure_seen(object *op) {
  652.   player *pl;
  653.  
  654.   for (pl = first_player; pl; pl = pl->next)
  655.     if (pl->ob->map == op->map &&
  656.         pl->ob->y + WINUPPER <= op->y && pl->ob->y + WINLOWER >= op->y &&
  657.         pl->ob->x + WINLEFT  <= op->x && pl->ob->x + WINRIGHT >= op->x)
  658.       pl->blocked_los[5 + op->x - pl->ob->x][5 + op->y - pl->ob->y] = 0;
  659. }
  660.  
  661. /*
  662.  * make_sure_not_seen: The object which is supposed to be visible through
  663.  * walls has just been removed from the map, so update the los of any
  664.  * players within its range
  665.  */
  666.  
  667. void make_sure_not_seen(object *op) { 
  668.   player *pl;
  669.   for (pl = first_player; pl; pl = pl->next)
  670.     if (pl->ob->map == op->map &&
  671.         pl->ob->y + WINUPPER <= op->y && pl->ob->y + WINLOWER >= op->y &&
  672.         pl->ob->x + WINLEFT  <= op->x && pl->ob->x + WINRIGHT >= op->x)
  673.       pl->do_los = 1;
  674. }
  675.